<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import { Base } from '../threejs/base';
import * as THREE from 'three';
import fish from '../assets/fish.svg';
import snake from '../assets/snake.png';
import { gsap } from "gsap";
class Demo extends Base {
  mesh;
  m;
  time;
  mouse;
  controls = { color: 0xff0000 };
  geometry = { Geometry: 1 };
  initGui() {
    const g = this.gui.addFolder('调整这里试试');
    let colorChange = g.addColor(this.controls, 'color').name('色值');
    colorChange.onChange((value) => {
      console.log(value);
      for (let i = 0; i < this.scene.children.length; i++) {
        // 方式1
        // this.scene.children[i].material.uniforms.uColor.value.set(value); // 改变颜色为绿色
        // 方式2
        var newColor = new THREE.Color(this.controls.color);
        // 更新材质的颜色
        console.log(newColor);
        this.scene.children[i].material.uniforms.uColor.value.copy(newColor); // 如果颜色是uniform
      }
    });
    g.open();
  }

  initShader() {
    this.mouse = new THREE.Vector2();
    this.raycaster = new THREE.Raycaster();
    this.camera.position.set(0, 0, 4);
    this.camera.lookAt(new THREE.Vector3());
    this.renderer.setClearColor(0x160016, 1);
    window.addEventListener("mousemove", (e) => {
      this.mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
      this.mouse.y = (-e.clientY / window.innerHeight) * 2 + 1;
      // console.log(this.mouse)
    });
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        // modelPosition.y += 0.08 * sin(modelPosition.x * PI * 2.0 + uTime);
        // modelPosition.y += 0.1 * sin(modelPosition.z * PI * 1.5 + uTime);
        // float strength = uv.x;
        float strength = smoothstep(0.0, 1.0, uv.x);
        vStrength = strength;
        
        // modelPosition.y += 0.3 * strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        // vec4 color = texture2D(uTexture, vUv);
        // gl_FragColor = vec4(color);
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
      }
    `,-2,1);
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        // modelPosition.y += 0.08 * sin(modelPosition.x * PI * 2.0 + uTime);
        // modelPosition.y += 0.1 * sin(modelPosition.z * PI * 1.5 + uTime);
        float strength = uv.x;
        // float strength = smoothstep(0.0, 1.0, uv.x);
        vStrength = strength;
        
        // modelPosition.y += 0.3 * strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        // vec4 color = texture2D(uTexture, vUv);
        // gl_FragColor = vec4(color);
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
      }
    `,-2,0);
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float strength = smoothstep(0.3, 0.7, uv.x);
        vStrength=strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
      }
    `,-2,-1);
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float strength = smoothstep(0.8, 0.2, uv.x);
        vStrength=strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
      }
    `,-0.5,1);
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float strength = abs(uv.x - 0.5);
        vStrength=strength;
        modelPosition.y += 0.3 * strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
      }
    `,-0.5,0);
    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float strength = smoothstep(0.3, 0.0, abs(uv.x - 0.5 + 0.5 * sin(uTime)));
        vStrength=strength;
        modelPosition.y += 0.3 * strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        // vec3 color = vec3(vStrength);
        // gl_FragColor = vec4(color,1.0);
        gl_FragColor = texture2D(uTexture, vUv);
      }
    `,-0.5,-1);


    this.ini01(`
      uniform float uTime;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float dist = distance(uv, vec2(0.5));
        float strength = dist;
        vStrength = strength;
        modelPosition.y += 0.3 * strength;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        vec3 color = vec3(vStrength);
        gl_FragColor = vec4(color,1.0);
        // gl_FragColor = texture2D(uTexture, vUv);
      }
    `,1,1);
    this.ini01(`
      uniform float uTime;
      uniform vec2 uMouse;
      varying vec2 vUv;
      const float PI = 3.1415926;
      varying float vStrength;
      void main() {
        vUv = uv;
        vec4 modelPosition = modelMatrix * vec4(position, 1.0);
        float dist = distance(uv, uMouse);
        // float strength = dist;
        float strength = smoothstep(0.4, 0.0,dist);
        vStrength = strength;
        modelPosition.z += 0.3 * strength * sin(uTime) ;
        gl_Position = projectionMatrix * viewMatrix * modelPosition;
      }
    `,`
      varying vec2 vUv;
      uniform sampler2D uTexture;
      varying float vStrength;
      void main() {
        // vec3 color = vec3(vStrength);
        // gl_FragColor = vec4(color,1.0);
        gl_FragColor = texture2D(uTexture, vUv);
      }
    `,1,0);
  }
  
  ini01(vertexShader,fragmentShader,x,y) {
    const geometry = new THREE.PlaneGeometry(1, 1, 30, 30);
    let material = new THREE.ShaderMaterial({
      uniforms: {
        uTime: { value: 0 },
        uColor: { value: new THREE.Color(0xff0000) },
        uTexture: {
          // value: new THREE.TextureLoader().load('../assets/snake.png'),
          value: new THREE.TextureLoader().load(snake),
        },
        uMouse: { value: new THREE.Vector2(0.5, 0.5) },
      },
      vertexShader,
      fragmentShader,
      side:THREE.DoubleSide,
      // transparent: true,
      // depthTest: false,
      // depthWrite: false,
      // wireframe: true,

    });
    const mesh = new THREE.Mesh(geometry, material);
    mesh.position.x=x
    mesh.position.y=y
    this.scene.add(mesh);
  }

  renderContent() {
    // this.time += 0.05;
    let time = this.clock.getElapsedTime();
    for (let i = 0; i < this.scene.children.length; i++) {
      this.scene.children[i].material.uniforms.uTime.value = time;
      this.scene.children[i].rotation.y = time / 100;
    }

    this.raycaster.setFromCamera(this.mouse, this.camera);
    const intersect = this.raycaster.intersectObject(this.scene);
    if (intersect.length > 0) {
      console.log(intersect[0]);
      intersect[0].object.material.uniforms.uMouse.value = intersect[0].uv;
    }
  }
}

let ins;
const dom = ref();
let run=()=>{
  console.log(ins.scene.children[0].material.uniforms.vProgress)
  gsap.to(ins.scene.children[0].material.uniforms.vProgress, {
    value: 1,
    onComplete: () => {
      // animating = false;
      // geometry.attributes.position.array = geometryAttributes[current];
      // geometry.attributes.position.needsUpdate = true;
      // material.uniforms.uColor.value = color;
      // material.uniforms.uProgress.value = 0;
      // ins.scene.children[0].material.uniforms.vProgress.value=0
    },
  });
}
onMounted(() => {
  ins = new Demo().init(dom.value);
});
onUnmounted(() => {
  ins.dispose();
});

const text = `
本示例主要学习了通过 uniforms 向着色器传递数据。示例主要代码如下：
\`\`\`
const m = new THREE.ShaderMaterial({
  uniforms: {
    uColor: { value: new THREE.Color(0xff0000) }
  },
  vertexShader: \`
    void main() {
      
      // position 是顶点的local坐标(Model坐标)
      // Model坐标 * ModelMatrix = World坐标；World坐标 * ViewMatrix = Camera坐标；Camera坐标 * ProjectionMatrix = 投影坐标

      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }\`,
  fragmentShader: \`
    uniform vec3 uColor;  // 接收 uniforms 传过来的数据
    
    void main() {
      gl_FragColor = vec4(uColor, 1.0);
    }\`
});
\`\`\`
`;
</script>

<template>
  <div class="shader-box" ref="dom" @click="run"></div>
  <v-md-preview :text="text"></v-md-preview>
</template>

<style scoped></style>
